package com.pig4cloud.pigx.contract.thread.rule;

import com.pig4cloud.pigx.common.customize.contants.SystemConfigConstants;

import java.math.BigDecimal;

/**
 * 虚拟最新成交记录 生成规则
 */
public class SaveTradeRule {

	/**
	 * 初始拟定成交数量平均为 100 `USDT`
	 */
	private static final BigDecimal TRANSACTION_PRICE = new BigDecimal("100");

	/**
	 * 成交数量10倍暴击概率
	 */
	private static final int TEN_MULTIPLE_CRITICAL_HIT_PROBABILITY = 5;

	/**
	 * 成交数量5倍暴击概率
	 */
	private static final int FIVE_MULTIPLE_CRITICAL_HIT_PROBABILITY = 12;

	/**
	 * 成交数量2倍暴击概率
	 */
	private static final int TWO_MULTIPLE_CRITICAL_HIT_PROBABILITY = 25;

	/**
	 * 根据币对最新价格获取随机成交数量
	 * @param lastPrice 最新价
	 * @return 成交数量
	 */
	public static BigDecimal getNum(BigDecimal lastPrice,BigDecimal minOrderNum,BigDecimal maxOrderNum) {
		BigDecimal divide = TRANSACTION_PRICE.divide(
				lastPrice,
				SystemConfigConstants.amountScale,
				SystemConfigConstants.mainCurRoundingMode);
		BigDecimal num = BigDecimal.valueOf(Math.random() * divide.floatValue() + minOrderNum.floatValue());
		double random = Math.random() * 100;
		if (lastPrice.compareTo(BigDecimal.TEN) > 0) {
			num = num.multiply(new BigDecimal("2"));
		}
		if (lastPrice.compareTo(new BigDecimal("100")) > 0) {
			num = num.multiply(new BigDecimal("3"));
		}
		if (lastPrice.compareTo(new BigDecimal("1000")) > 0) {
			num = num.multiply(new BigDecimal("4"));
		}
		if (lastPrice.compareTo(new BigDecimal("10000")) > 0) {
			num = num.multiply(new BigDecimal("2"));
		}
		if (random <= TEN_MULTIPLE_CRITICAL_HIT_PROBABILITY) {
			return num.multiply(new BigDecimal("10"));
		}
		if (random <= FIVE_MULTIPLE_CRITICAL_HIT_PROBABILITY) {
			return num.multiply(new BigDecimal("5"));
		}
		if (random <= TWO_MULTIPLE_CRITICAL_HIT_PROBABILITY) {
			return num.multiply(new BigDecimal("2"));
		}
		return clamp(num,minOrderNum,maxOrderNum);
	}

	/**
	 * 根据下单币种的`市场价/最大最小下单`数量不同,采用clamp算法来决定最终下单数量
	 * @param val 预计下单数量
	 * @param min 最小下单数量
	 * @param max 最高下单数量
	 * @return 最终下单数量
	 */
	public static BigDecimal clamp(BigDecimal val, BigDecimal min, BigDecimal max) {
		return BigDecimal.valueOf(Math.max(min.floatValue(), Math.min(max.floatValue(), val.floatValue())));
	}
}
